<?php
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
*/
namespace app\web\controller;
use app\common\Base;

class Contest extends Base {

    public function __construct(\think\Request $request = null) {
        parent::__construct($request);
        $this->assign('cid', input('cid',0,'intval'));
        $this->assign('is_contest_create', $this->is_contest_create());
        $this->assign('is_contest_admin', $this->have_power(4)||$this->have_power(3));
        $this->assign('timeleft', $this->get_contest_left_time(input('cid',null)));
    }
    private function is_contest_create(){
        $cid= input('cid',null);
        if($cid==null) return false;
        $info=db('contest')->find($cid);
        if(empty($info)){
            return false;
        }
        if($info['user_id']== $this->user_id) {
            return true;
        }else {
            return FALSE;
        }
    }

    public function show_nav($cid) {    //比赛信息及比赛导航栏
        $list = db('contest')->where(['contest_id' => $cid])->select();
        $now_time = date('Y-m-d H:i:s',time());  //获取当前时间（日期形式）
        $seal_time = $list[0]['seal_time']; //封榜时间
        $unmake_time = $list[0]['unmake_time']; //解榜时间
        $seal = false;
        if(strcmp($now_time,$seal_time)>0 && strcmp($now_time,$unmake_time)<0) $seal=true;
        $this->assign('seal', $seal);   //封榜时，显示封榜字样
        $this->assign('list', $list);
        $this->assign('tagval',3);  //对应比赛界面的时候，OJ导航栏‘比赛’高亮
    }
    public function index() {   //比赛页信息浏览
        $list = db('contest')->where("defunct='N'")->order('start_time desc')->paginate(15);
        $page = $list->render();
        $this->assign('list', $list);
        $this->assign('page', $page);
        $this->assign('tagval',3);
        return $this->fetch();
    }
    public function judge_start($cid) 
    {
        $tmp_time = db('contest')->where(['contest_id' => $cid])->field('start_time,user_id')->select();
        $now_time = date('Y-m-d H:i:s',time());  //获取当前时间（日期形式）
        $start_time = $tmp_time[0]['start_time'];
        if(strcmp($now_time,$start_time)<=0 && $this->user_id != $tmp_time[0]['user_id']) { //如果现在时间小于比赛开始时间而且这个用户不是创建比赛的用户，则问题列表跳转到首页
            $contest_start=false;
            $this->assign('contest_start',$contest_start);
            return $this->redirect('web/contest/show',['cid'=>$cid]);
        }
    }
    public function show($cid) {    //显示前台对应cid的比赛的界面展示的方法

        // dump();
        $this->judge($cid); //
        $this->show_nav($cid);
        $tmp_time = db('contest')->where(['contest_id' => $cid])->field('start_time,user_id,unmake_time')->select();
        $now_time = date('Y-m-d H:i:s',time());  //获取当前时间（日期形式）
        $start_time = $tmp_time[0]['start_time'];
        $unmake_time = $tmp_time[0]['unmake_time'];
        // dump($tmp_time[0]['user_id']);
        // dump($this->user_id);
        $problem_link = false; //是否显示题目的原链接
        if(strcmp($now_time,$unmake_time)>=0) $problem_link = true; //如果现在时间大于解榜时间，则显示
        $this->assign('problem_link',$problem_link);
        if(strcmp($now_time,$start_time)<=0 && $this->user_id != $tmp_time[0]['user_id']) { //如果现在时间小于比赛开始时间而且这个用户不是创建比赛的用户，则问题列表不显示
            $problem_list="";
            $contest_start=false;
            $this->assign('contest_start',$contest_start);
        }
        else {
            $problem_list = db('contest_problem')->where(['contest_id' => $cid])->order('num asc')->select();
            $user_id = $this->user_id;
            // dump($problem_list);
            foreach ($problem_list as $key => $value) {
                if (empty($value['alias'])) { //如果问题别名为空，则将原本的问题的题目显示上去
                    $tmp = db('problem')->where(['problem_id' => $value['problem_id']])->field('title')->select();
                    $problem_list[$key]['alias'] = $tmp[0]['title'];
                }
                $problem_list[$key]['char_num'] = chr(65 + $problem_list[$key]['num']);
                $ac = db('solution')->where(['contest_id' => $cid, 'num' => $key, 'result' => 4,'user_id'=>$user_id])->count();
                $submit = db('solution')->where(['contest_id' => $cid, 'num' => $key,'user_id'=>$user_id])->count();
                if($ac>0) $problem_list[$key]['ac']=1;  //如果这个题过了
                else if($submit>0) $problem_list[$key]['ac']=-1;  //如果这个题没过
                else $problem_list[$key]['ac']=0;   //没提交
                $problem_list[$key]['submit'] = db('solution')->where(['contest_id' => $cid, 'num' => $key, 'result' => 4])->count();
                // $problem_list[$key]['ac'] 
                // dump($problem_list[$key]['ac']);
                $problem_list[$key]['all'] = db('solution')->where(['contest_id' => $cid, 'num' => $key])->count();
            }
    }
        // dump($problem_list);
        $this->assign('problem', $problem_list);
        return $this->fetch();
    }

    public function problem($cid, $num) { //对应cid比赛的第num题
        $this->judge($cid);
        $this->show_nav($cid);
        $this->judge_start($cid);
        $this->assign('num', $num);
        $num = ord($num) - 65;
        // dump($num);
        $contest_list = ['contest_id' => $cid, 'num' => $num];
        $problem_id = db('contest_problem')->where($contest_list)->field('problem_id')->select();
        $all_problem_link = db('contest_problem')->where(['contest_id'=>$cid])->field('problem_id,num,problem_title,alias')->order('num')->select();
        $problem_id = $all_problem_link[$num]['problem_id'];
        // dump($problem_id);
        if(empty($all_problem_link[$num]['alias'])) {
        $all_problem_link[$num]['alias'] = $all_problem_link[$num]['problem_title'];
        db('contest_problem')->update(['problem_id'=>$problem_id,'contest_id'=>$cid,'alias'=>$all_problem_link[$num]['alias']]);
        }
        $problem = db('problem')->where(['problem_id' => $problem_id])->select();
        // dump($all_problem_link);
        $problem[0]['title'] = $all_problem_link[$num]['alias'];
        // dump($problem);
        $is_login = empty($_SESSION['user_id']) ? 0 : 1;
        foreach ($all_problem_link as $key => $value) {
            $all_problem_link[$key]['num']=chr($value['num']+65);
        }
        // dump($all_problem_link);
        $this->assign('is_login', $is_login);
        $this->assign('problemitem', $problem[0]);
        $this->assign('cid',$cid);
        $this->assign('all_problem_link',$all_problem_link);
        return $this->fetch();
    }

    public function query_status_data($cid) {   //比赛提交状态查询条件
        $res = array();
        $pid = input('get.pid', -1, 'int');

        // $user_id_now = $this->user_id;
        $user_id = input('get.user_id', '', 'trim');//trim去除字符串两侧空格
        $language = input('get.language', -1, 'intval');
        $res['contest_id'] = $cid;
        $result = input('get.result', -1, 'intval');
        if ($pid != - 1) {
            $tmp = db('contest_problem')->where(['contest_id' => $cid, 'num' => $pid])->field('problem_id')->select();
            $res['problem_id'] = $tmp[0]['problem_id'];
            $res['pid'] = $pid;
        } else {
            $res['pid'] = - 1;
        }
        if ($user_id != '') $res['user_id'] = $user_id;
        if ($language != - 1) $res['language'] = $language;
        if ($result != - 1) $res['result'] = $result;
        return $res;
    }

    public function status($cid) {  //比赛提交状态
        $this->judge($cid);
        $this->show_nav($cid);
        $this->judge_start($cid);
        $data = $this->query_status_data($cid);
        $pid = $data['pid'];
        unset($data['pid']);

        $list = db('contest')->where(['contest_id'=>$cid])->field('unmake_time,user_id')->select();
        $now_time = date('Y-m-d H:i:s',time());  //获取当前时间（日期形式）
        $unmake_time = $list[0]['unmake_time'];
        $query = ['contest_id' => input('get.contest_id'), 'pid' => input('get.pid', -1, 'intval'), 'userid' => input('get.userid', '', 'trim'), 'result' => input('get.result', -1, 'intval'), 'language' => input('get.language', -1, 'intval') ];


        // dump($data);

        if(strcmp($now_time,$unmake_time)>0 || $this->user_id == $list[0]['user_id']) { //如果现在已经解榜了或者拥有用户管理权限，或者是比赛的拉题人的话，就可以浏览所有提交状态
            $urldata = db('solution')->where($data)->order('in_date desc')->paginate(15, false, array('query' => $query));
        } else{  //否则只能查看自己的提交状况
            if(!isset($data['user_id'])||$data['user_id'] != $this->user_id) {
                $data['user_id'] =$this->user_id;
                $urldata = db('solution')->where($data)->order('in_date desc')->paginate(15, false, array('query' => $query));
                $contest_unmake = false;
                $this->assign('contest_unmake',$contest_unmake);
            }
        }
        $urldata = db('solution')->where($data)->order('in_date desc')->paginate(15, false, array('query' => $query));
        $num = db('contest_problem')->where(['contest_id' => $cid])->field('num,alias')->order('num')->select();
        $data['problem_id'] = intval($pid);
        $page = $urldata->render();
        $this->assign('lang_mask',config('OJ_LANGMASK'));
        $this->assign('data', $data); //选择状态列表
        $this->assign('problem_chr_id', $num); //题目ID下拉框传值 A B C..
        $this->assign('lang', config('oj_language_list')); //提交语言 c？c++？java？
        $this->assign('resultset', config('oj_result')); //提交结果，ac，wa？
        // $this->assign('list',$list);   //比赛contest表 开始时间结，束时间等
        $this->assign('urldata', $urldata); //状态列表
        $this->assign('page', $page);
        return $this->fetch();
    }

    private function my_sort($a, $b) { //排序规则
        if ($a['count_ac'] == $b['count_ac']) return $a['time'] < $b['time'] ? -1 : 1;
        return $a['count_ac'] < $b['count_ac'];
    }
    private function changeTimeType($seconds){ //将秒转换为时分秒格式
        if($seconds >3600) {
        $hours =intval($seconds/3600);
        $minutes = $seconds % 3600;
        $time = $hours.":".gmstrftime('%M:%S',$minutes);
        } else {
            $time = gmstrftime('%H:%M:%S',$seconds);
        }
        return $time;
    }
    private function seal_ranklist($cid) {  //封榜排名
        $contest_start_query = db('contest')->where(['contest_id' => $cid])->field('start_time,seal_time,unmake_time')->select();  //查询比赛开始时间
        $start_time = strtotime($contest_start_query[0]['start_time']);//将比赛开始时间由年月日时分秒转换为时间戳(秒)
        $now_time = date('Y-m-d H:i:s',time());  //获取当前时间（日期形式）
        $seal_time = $contest_start_query[0]['seal_time'];
        $unmake_time = $contest_start_query[0]['unmake_time'];
        $seal = false;
        if(strcmp($now_time,$seal_time)>0 && strcmp($now_time,$unmake_time)<0) $seal=true;
        $user_status = db('solution')->where(['contest_id' => $cid])->field('user_id,result,num,in_date')->order('in_date')->select();//获取cid比赛的用户名，提交结果，提交题目，提交时间字段
        // dump($user_status);
        $is_ac = array(); //该用户该题是否ac 二维
        $submit_times = array(); //该用户该题提交次数 二维
        $last_submit_times = array(); //该用户封榜后该题提交次数 二维
        $time = array(); //该用户所用总时间
        $count_ac = array(); //该用户ac总题量
        $problem_time = array(); //，该用户该题所用时间， 二维
        $is_first_ac = array(); //该用户是否是该题第一个ac的人 二维
        $problem_first = array(); //该题是否被AC
        foreach ($user_status as $key => $value) {
            $user_id = $value['user_id'];
            $is_ac[$user_id] = array();
            $submit_times[$user_id] = array();
            $problem_time[$user_id] = array();
            $is_first_ac[$user_id] = array();
        }
        // $last_submit_times = array(); //该用户封榜后该题提交次数 二维
        foreach ($user_status as $key => $value) {
            $user_id = $value['user_id']; //提交用户
            $num = $value['num']; //对应题号
            $in_date = $value['in_date']; //提交时间
            $result = $value['result'] == 4; //提交结果
            // dump($is_ac[$user_id]);
            if (!isset($is_ac[$user_id][$num])) $is_ac[$user_id][$num] = false;
            if ($is_ac[$user_id][$num] == true) { //如果该用户该题已经AC
                continue;
            }
            if($seal==true && strcmp($in_date,$seal_time)>=0 && strcmp($in_date,$unmake_time)<=0)  {//提交时间大于封榜时间
                if (!isset($submit_times[$user_id][$num])) $submit_times[$user_id][$num] = 0;
                if(!isset($last_submit_times[$user_id][$num])) $last_submit_times[$user_id][$num]=0;
                $last_submit_times[$user_id][$num]++;
            }

            else if (!$is_ac[$user_id][$num] && $result == false) { //如果该用户该题尚未AC，且此次依然未AC
                if (!isset($submit_times[$user_id][$num])) $submit_times[$user_id][$num] = 0;
                if (!isset($problem_time[$user_id][$num])) $problem_time[$user_id][$num] = 0;
                $submit_times[$user_id][$num]+= 1;
                // $problem_time[$user_id][$num]+= 20 * 60;
            } else if (!$is_ac[$user_id][$num] && $result == true) { //如果该用户该题尚未AC，此次AC
                if (!isset($submit_times[$user_id][$num])) $submit_times[$user_id][$num] = 0;
                if (!isset($problem_first[$num])) {
                    $problem_first[$num] = true; //该题一血已经被拿
                    $is_first_ac[$user_id][$num] = 1; //标记该用户该题拿了一血
                    
                }
                $problem_time[$user_id][$num]= strtotime($in_date) - $start_time;
                $is_ac[$user_id][$num] = true;
            }
        }
        $problem_num = db('contest_problem')->where(['contest_id' => $cid])->field('num')->order('num asc')->select();
        // dump($problem_num);
        $distinct_user = db('solution')->where(['contest_id' => $cid])->distinct(true)->field('user_id')->select();
        // dump($distinct_user);
        $user = array();
        foreach ($distinct_user as $key => $u) {
            $user[$key] = array();
            $user_id = $u['user_id'];
            if (!isset($time[$user_id])) $time[$user_id] = 0;
            if (!isset($count_ac[$user_id])) $count_ac[$user_id] = 0;
            foreach ($problem_num as $v) {
                $num = $v['num'];
                // if(!isset($problem_time[$user_id][$num]))
                //     $problem_time[$user_id][$num]=0;
                if (!isset($submit_times[$user_id][$num])) $submit_times[$user_id][$num] = 0;
                if($seal == true &&!isset($last_submit_times[$user_id][$num])) $last_submit_times[$user_id][$num]=0;
                if (!isset($is_first_ac[$user_id][$num])) $is_first_ac[$user_id][$num] = false;
                if (!isset($is_ac[$user_id][$num])) $is_ac[$user_id][$num] = false;
                if ($is_ac[$user_id][$num] == true) {
                    $time[$user_id]+= $problem_time[$user_id][$num]+20*60*$submit_times[$user_id][$num];
                    // dump($problem_time[$user_id][$num]);
                    $problem_time[$user_id][$num]=$this->changeTimeType($problem_time[$user_id][$num]);
                    $count_ac[$user_id]++;
                }
            }
            $user[$key]['user_id'] = $user_id;
            $user[$key]['count_ac'] = $count_ac[$user_id];
            $user[$key]['time'] = $time[$user_id];
        }
        usort($user, array($this, 'my_sort'));
        foreach ($user as $key => & $value) {
            $nick = db('users')->where(['user_id' => $value['user_id']])->field('nick')->select();
            $value['nick'] = $nick[0]['nick'];
            $value['time'] = $this->changeTimeType($value['time']);
        }
        $count_problem = db('contest_problem')->where(['contest_id' => $cid])->count();
        $this->assign('count_problem', $count_problem);
        $this->assign('num', $problem_num);
        $this->assign('user', $user);
        $this->assign('is_ac', $is_ac);
        $this->assign('submit_times', $submit_times);
        // dump($seal);
        if($seal == true) {
        $this->assign('last_submit_times', $last_submit_times);
        }
        $this->assign('problem_time', $problem_time);
        $this->assign('is_first_ac', $is_first_ac);
    }

    public function ranklist($cid) {    //比赛榜单
        $this->judge($cid);
        $this->show_nav($cid);
        $this->judge_start($cid);
        $this->seal_ranklist($cid);
        $this->assign("user_id",$this->user_id);
        return $this->fetch();
    }
    public function input_password($cid) { //私人比赛输入密码
        $this->assign('navhide',true);
        $this->show_nav($cid);
        // $this->judge($cid);
        return $this->fetch();
    }
    public function subpasswd() {   //提比赛交密码
        if (!$this->is_login) {
            return json(['result' => - 1, 'msg' => '请先登录账户!']);
        }
        $passwd = input('post.contest_password');
        $cid = input('cid');
        $rel_passwd = db('contest')->where(['contest_id' => $cid])->field('password')->select();
        if (isset($rel_passwd[0]['password']) && $rel_passwd[0]['password'] == $passwd) {
            $_SESSION['cid-'.$cid] = $passwd;
            return json(['result' => 1, 'url' => url('web/contest/show', ['cid' => $cid]) ]);
        }
        return json(['result' => 0]);
    }
    public function notice(){ //发布通知
        $cid= input('cid',NULL);
        $content= input('content',null);
        if(!$this->is_login){
            $this->error_ui('请先登录');
        }
        if($cid==NULL){
            $this->error_ui('比赛ID不能为空');
        }
        if($content==NULL){
            $this->error_ui('内容不能为空');
        }
        $contest_info=db('contest')->find($cid);
        if(empty($content)){
            $this->error_ui('该比赛不存在');
        }
        if($this->user_id==$contest_info['user_id']||($this->have_power(3)&&$this->have_power(4))){
            $data['pre']=-2;
            $data['cid']=$cid;
            $data['user_id']= $this->user_id;
            $data['in_time']=time();
            $data['content']=$content;
            $data['ip']= request()->ip();
            $data['reply_time']=time();
            db('contest_discuss')->insert($data);
            $this->success_ui('通知成功',url('web/Contest/show',['cid'=>$cid]));
        }
        else
        {
            $this->error_ui('没有权限');
        }
    }
    
    /**
     *  根据cid 获取最新信息
     */
    public function getnotice(){//获取通知
        $cid=input('cid',null);
        $ret['code']=1;
        if($cid==null){
            $ret['msg']='CID 为空,error';
            return json($ret);
        }
        $condition['pre']=-2;
        $condition['cid']=$cid;
        $contest_info=db('contest')->find($cid);
        if(empty($contest_info)){
            $ret['msg']='比赛不存在';
            return json($ret);
        }
        $info=db('contest_discuss')->where($condition)->select();
        $start_time= strtotime($contest_info['start_time']);
        $end_time= strtotime($contest_info['end_time']);
        $now_time=time();
        if($now_time>=$start_time&&$now_time<=$end_time){
            foreach ($info as $v){
                $cookie_notice= cookie($cid.$v['id']);
                if($cookie_notice==null){
                    cookie($cid.$v['id'],'1',36000);
                    $ret['code']=0;
                    $ret['content']=$v['content'];
                    return json($ret);
                }
            }
            $ret['msg']='没有新的消息';
            return json($ret);
        }else {
            $ret['msg']='该比赛已经结束';
            return json($ret);
        }
    }
}
